using System;
using UnityEngine;

[Serializable]
[AddComponentMenu("Third Person Camera/Spring Follow Camera")]
public class SpringFollowCamera : MonoBehaviour
{
	public Transform target;

	public float distance;

	public float height;

	public float smoothLag;

	public float maxSpeed;

	public float snapLag;

	public float clampHeadPositionScreenSpace;

	public LayerMask lineOfSightMask;

	private bool isSnapping;

	private Vector3 headOffset;

	private Vector3 centerOffset;

	private Vector3 velocity;

	private float targetHeight;

	public SpringFollowCamera()
	{
		distance = 4f;
		height = 1f;
		smoothLag = 0.2f;
		maxSpeed = 10f;
		snapLag = 0.3f;
		clampHeadPositionScreenSpace = 0.75f;
		headOffset = Vector3.zero;
		centerOffset = Vector3.zero;
		velocity = Vector3.zero;
		targetHeight = 100000f;
	}

	public void Awake()
	{
		CharacterController characterController = target.GetComponent<Collider>() as CharacterController;
		if ((bool)characterController)
		{
			centerOffset = characterController.bounds.center - target.position;
			headOffset = centerOffset;
			ref Vector3 reference = ref headOffset;
			Vector3 max = characterController.bounds.max;
			float y = max.y;
			Vector3 position = target.position;
			reference.y = y - position.y;
		}
		if (!target)
		{
		}
	}

	public void LateUpdate()
	{
		Vector3 vector = target.position + centerOffset;
		Vector3 headPos = target.position + headOffset;
		targetHeight = vector.y + height;
		if (Input.GetButton("Fire2") && !isSnapping)
		{
			velocity = Vector3.zero;
			isSnapping = true;
		}
		if (isSnapping)
		{
			ApplySnapping(vector);
		}
		else
		{
			ApplyPositionDamping(new Vector3(vector.x, targetHeight, vector.z));
		}
		SetUpRotation(vector, headPos);
	}

	public void ApplySnapping(Vector3 targetCenter)
	{
		Vector3 position = transform.position;
		Vector3 vector = position - targetCenter;
		vector.y = 0f;
		float magnitude = vector.magnitude;
		Vector3 eulerAngles = target.eulerAngles;
		float y = eulerAngles.y;
		Vector3 eulerAngles2 = transform.eulerAngles;
		float y2 = eulerAngles2.y;
		y2 = Mathf.SmoothDampAngle(y2, y, ref velocity.x, snapLag);
		magnitude = Mathf.SmoothDamp(magnitude, distance, ref velocity.z, snapLag);
		Vector3 vector2 = targetCenter;
		vector2 += Quaternion.Euler(0f, y2, 0f) * Vector3.back * magnitude;
		vector2.y = Mathf.SmoothDamp(position.y, targetCenter.y + height, ref velocity.y, smoothLag, maxSpeed);
		vector2 = AdjustLineOfSight(vector2, targetCenter);
		transform.position = vector2;
		if (!(AngleDistance(y2, y) >= 3f))
		{
			isSnapping = false;
			velocity = Vector3.zero;
		}
	}

	public Vector3 AdjustLineOfSight(Vector3 newPosition, Vector3 target)
	{
		RaycastHit hitInfo = default(RaycastHit);
		Vector3 result;
		if (Physics.Linecast(target, newPosition, out hitInfo, lineOfSightMask.value))
		{
			velocity = Vector3.zero;
			result = hitInfo.point;
		}
		else
		{
			result = newPosition;
		}
		return result;
	}

	public void ApplyPositionDamping(Vector3 targetCenter)
	{
		Vector3 position = transform.position;
		Vector3 vector = position - targetCenter;
		vector.y = 0f;
		Vector3 vector2 = vector.normalized * distance + targetCenter;
		Vector3 vector3 = default(Vector3);
		vector3.x = Mathf.SmoothDamp(position.x, vector2.x, ref velocity.x, smoothLag, maxSpeed);
		vector3.z = Mathf.SmoothDamp(position.z, vector2.z, ref velocity.z, smoothLag, maxSpeed);
		vector3.y = Mathf.SmoothDamp(position.y, targetCenter.y, ref velocity.y, smoothLag, maxSpeed);
		vector3 = AdjustLineOfSight(vector3, targetCenter);
		transform.position = vector3;
	}

	public void SetUpRotation(Vector3 centerPos, Vector3 headPos)
	{
		Vector3 position = transform.position;
		Vector3 vector = centerPos - position;
		Quaternion lhs = Quaternion.LookRotation(new Vector3(vector.x, 0f, vector.z));
		Vector3 forward = Vector3.forward * distance + Vector3.down * height;
		transform.rotation = lhs * Quaternion.LookRotation(forward);
	}

	public float AngleDistance(float a, float b)
	{
		a = Mathf.Repeat(a, 360f);
		b = Mathf.Repeat(b, 360f);
		return Mathf.Abs(b - a);
	}

	public void Main()
	{
	}
}
